#ifndef _Config_h_
#define _Config_h_

/*
  There are currently 2 types of config.
  1) XML configs per window.  These are managed through the PowerWindow class automatically.  The code in project_shared.h should be moved here.
  2) Straight lists of '=' values as implemented in ide/Core/Workspace.cpp.  Unlike the documented config options, this shows the use of a Singleton to abstract when the Nest is actually loaded.
  
  General Commentary on methods:
  - I like the flexibility of XML and its standardization.  Everyone can read the darn things.  I like that they open in IE if you click on them.
    But I suspect the overhead is overkill for the little collection of window attributes.  Since they are hit on open/close, there is no discernable delay to the user.
    Since each window manages its own configuration, you don't loose information if the app is killed, shutdown or closed improperly.  This (to me) is a great feature.  It is very annoying to have a window "forget" where it was last, or what size it was, or a font, etc.  I don't know why.  I think Windows creates the illusion that the application "cares" and recognizes our concerns.  It "listens" to us.  When it forgets a setting, we are jarred back to the reality that computers are really just stupid boxes.
    Another nicety of having separate xmls per window is that as the functionality increases over time, the main window config does not bog down, and there is less risk of damage to it due to some funky window storing binary or such.  The main window is sancrosanct and must always open.
    
    The new list form of keypairs separated by equals signs came about from examining the Nest object in the U++ ide code.  It is fast and uses a singleton, and I may switch all config files to this if the performance is noticable.  The number of Option values in the project can be expected to be considerable, because configurability is a core feature.
    I don't like the "var" extension and will switch to ini just so most windows boxes will open in text editors.
    
		if(!LoadVars(arg[0])) {
		if(build)
			Puts("TheIDE: Invalid assembly\n");
		else
			Exclamation("Invalid assembly!");
		SetExitCode(2);
		return;

*/

bool SaveVarFile(const char *filename, const VectorMap<String, String>& var)
{
	FileOut out(filename);
	for(int i = 0; i < var.GetCount(); i++)
		out << var.GetKey(i) << " = " << AsCString(var[i]) << ";\n";
	out.Close();
	return !out.IsError();
}

bool LoadVarFile(const char *name, VectorMap<String, String>& _var)
{
	try {
		VectorMap<String, String> var;
		String env = LoadFile(name);
		CParser p(env);
		while(!p.IsEof()) {
			String v = p.ReadId();
			p.Char('=');
			if(p.IsString())
				var.GetAdd(v) = p.ReadString();
			else {
				String ln;
				while(p.PeekChar() != '\r' && p.PeekChar() != '\n' && p.PeekChar() != ';')
					ln.Cat(p.GetChar());
				var.GetAdd(v) = ln;
				p.Spaces();
			}
			p.Char(';');
		}
		_var = var;
		return true;
	}
	catch(...) {
		return false;
	}
}

class Nest {
	VectorMap<String, String> var;

public:

	bool Save(const char *path)
	{
		return SaveVarFile(path, var);
	}
	
	bool Load(const char *path)
	{
		return LoadVarFile(path, var);
	}
	
	String Get(const String& id)
	{
		return var.Get(id, String());
	}
	
	void Set(const String& id, const String& val)
	{
		var.GetAdd(id) = val;
	}

};

Nest& MainNest()
{
	return Single<Nest>();
}

struct SemiTextTest : public TextTest {
	virtual const char *Accept(const char *s) const;
};

Vector<String> SplitDirs(const char *s) {
	return Split(s, Single<SemiTextTest>());
}

const char *SemiTextTest::Accept(const char *s) const {
	if(*s != ';') return NULL;
	s++;
	while(*s == ' ') s++;
	return s;
};

String GetVar(const String& var) {
	return MainNest().Get(var);
}

Vector<String> GetUppDirs() {
	return SplitDirs(GetVar("UPP"));
}

static String varsname = "default";

String GetVarsName()
{
	return varsname;
}

String VarFilePath(String name) {
	return ConfigFile(name + ".ini"); // Changed from .var to .ini to take advantage of Windows default assocation to a text editor
}

String VarFilePath() {
	return VarFilePath(GetVarsName());
}

// Stolen from the code of Workspace.cpp.  Called from ide.cpp in the Main function
bool   LoadVars(const char *name) {
	varsname = (name && *name ? name : "default");
	return MainNest().Load(VarFilePath());
}

bool SaveVars(const char *name)
{
	if(!MainNest().Save(VarFilePath(name)))
		return false;
	varsname = name;
	return true;
}


void SetVar(const String& var, const String& val) {
	MainNest().Set(var, val);
	SaveVars(GetVarsName());
}


#endif
